/* vim: set ts=2 et sw=2 cindent fo=qroca: */

package com.globant.google.mendoza.command;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.globant.google.malbec.Encoder;
import com.globant.google.mendoza.MendozaServer;
import com.globant.google.mendoza.MendozaRequest;
import com.globant.google.mendoza.MendozaServerState;

/** Represents the validation of the signature command.
 */
public final class MendozaAssertSignatureCommand extends
MendozaBaseCommand {

  /** The class logger.
   */
  private static Log log = LogFactory.getLog(
      MendozaAssertSignatureCommand.class);

  /** Creates an instance of MendozaAssertSignatureCommand.
   *
   * @param mendozaRequest The mendoza server request.
   *
   * @param mendoza The mendoza server.
   *
   * @param mendozaState The mendoza server state
   */
   public MendozaAssertSignatureCommand(
       final MendozaRequest mendozaRequest, final MendozaServer mendoza,
       final MendozaServerState mendozaState) {
     super(mendozaRequest, mendoza, mendozaState);
     setName("Assert signature");
  }

  /** Executes the validation of the shopping cart signature.
   */
  public void execute() {
    log.trace("Entering execute");
    MendozaCommandResult result = new MendozaCommandResult();
    String commandResultMsg =
      "The shopping cart signature is OK.";
    try {
      if (getMendozaState().getCartSignature() == null) {
        log.trace("Leaving execute");
        throw new RuntimeException("No signature was found to validate.");
      }
      if (getMendozaState().getShoppingCart() == null) {
        log.trace("Leaving execute");
        throw new RuntimeException(
                "No cart found. Post encoded command not yet issued.");
      }
      if (isBadSignature(getMendozaState().getShoppingCart(),
          getMendozaState().getCartSignature())) {
        log.trace("Leaving execute");
        throw new RuntimeException(BAD_SIGNATURE_MSG);
      }
      result.setSuccess(commandResultMsg);
    } catch (RuntimeException e) {
      commandResultMsg = e.getMessage();
      result.setError(commandResultMsg);
    }
    setResult(result);
    logCommand(this);
    log.trace("Leaving execute");
  }

  /** Checks if the signature is invalid.
   *
   * @param source The plain cart.
   *
   * @param theSignature The received signature.
   *
   * @return Returns if the signature is not valid.
   */
  private boolean isBadSignature(final String source,
      final String theSignature) {
    log.trace("Entering isBadSignature");
    String expectedSignature =
      Encoder.sign(source, getMendozaState().getMerchantKey());
    boolean result = !theSignature.equals(expectedSignature);
    log.trace("Leaving isBadSignature");
    return result;
  }

  /** Bad sinature error message.
   */
  private static final String BAD_SIGNATURE_MSG = "Bad signature on cart.\n"
    + "This error message means the HMAC-SHA1 signature you generated for your"
    + " shopping cart XML doesn't match the signature expected by "
    + "Google Checkout.\nWhen verifying the authenticity of your Checkout "
    + "cart posts, Google requires that the XML carts you submit are signed "
    + "using HMAC-SHA1.\n(HMAC-SHA1 is a function that uses your Google "
    + "Checkout Merchant Key and each shopping cart to generate a unique,"
    + " secure signature.)\n"
    + "If you've incorrectly entered your Google Checkout Merchant Key in "
    + "your system, you'll receive this error message.\nThe Merchant Key you "
    + "use must match the Merchant Key in the Google Checkout Merchant "
    + "Center.\nAlso, if you're performing your own API integration,\nremove "
    + "any leading or trailing white space in the Merchant Key string when "
    + "you assign your Merchant Key to a variable in your code.\n"
    + "If you've confirmed that you're using the correct Merchant Key, and "
    + "if you aren't using a third party shopping cart provider,\nyou may "
    + "have implemented the signature generation incorrectly.\nFor more "
    + "information about generating signatures correctly with Google "
    + "Checkout, please review the Developer's Guide.";
}

